package com.heima.comment.service.impl;

import com.alibaba.cloud.commons.lang.StringUtils;
import com.alibaba.fastjson.JSON;
import com.heima.audit.baidu.BaiduTextScan;
import com.heima.comment.service.CommentRepayService;
import com.heima.feign.apis.user.UserFeignClient;
import com.heima.model.common.comment.dtos.CommentRepayDto;
import com.heima.model.common.comment.dtos.CommentRepayLikeDto;
import com.heima.model.common.comment.dtos.CommentRepayListDto;
import com.heima.model.common.comment.pojos.ApComment;
import com.heima.model.common.comment.pojos.ApCommentLike;
import com.heima.model.common.comment.vo.ApCommentVo;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.common.user.pojo.ApUser;
import com.heima.utils.common.AppThreadLocal;
import org.bson.types.ObjectId;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.mongodb.core.query.UpdateDefinition;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
public class CommentRepayServiceImpl implements CommentRepayService {

    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private UserFeignClient userFeignClient;

    @Autowired
    private BaiduTextScan baiduTextScan;
    /**
     * 保存评论列表
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult saveCommentRepay(CommentRepayDto dto) {
        //1.检查参数
        if (dto.getCommentId() == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        if (dto.getContent() != null && dto.getContent().length() > 140) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE, "评论内容不能超过140字");
        }

        //2.判断是否登录
        ApUser apUser = AppThreadLocal.getApUser();
        if (apUser == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }

        //2.5 判断如果是游客身份则不允许发表评论
        if(apUser.getId()==0){
            return  ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN,"请登录之后再来评论！！");
        }

        //3.查询用户信息------先从redis中查询，如果不存在再从用户微服务中去查询
        String apuserStr = redisTemplate.opsForValue().get("LOGIN_USER_" + apUser.getId());
        if(StringUtils.isBlank(apuserStr)){//如果为空，则表示第一次
            //则远程从用户服务中调取
            ResponseResult<ApUser> result = userFeignClient.findUserById(apUser.getId().longValue());
            if(result.getCode()==200 && result.getData()!=null){
                apUser=result.getData();

                //存入到redis中,并设置两个小时过期时间
                redisTemplate.opsForValue().set("LOGIN_USER_"+apUser.getId(), JSON.toJSONString(apUser),2, TimeUnit.HOURS);
            }
        }else{//表示不是第一次，则直接从redis中取出
            apUser= JSON.parseObject(apuserStr,ApUser.class);
        }

        //4.对评论信息进行安全过滤
        /**
         * 百度云审核
         * status=1 合规
         * status=2 不合规
         * status=3 疑似
         * status=4 审核失败
         */
        Integer status = baiduTextScan.textScan(dto.getContent());
        if(status != 1){
            return ResponseResult.errorResult(AppHttpCodeEnum.COMMENT_BLOCK);
        }

        //5.保存数据到mongo中
        ApComment apComment = new ApComment();
        apComment.setId(ObjectId.get().toHexString());
        apComment.setUserId(apUser.getId());
        apComment.setNickName(apUser.getName());
        apComment.setContent(dto.getContent());
        apComment.setTargetId(dto.getCommentId());
        apComment.setCreatedTime(new Date());
        apComment.setUpdatedTime(new Date());
        apComment.setImage(apUser.getImage());
        apComment.setLikes(0);
        apComment.setReply(0);

        mongoTemplate.insert(apComment);

        Query query = Query.query(Criteria.where("id").is(dto.getCommentId()));
        UpdateDefinition updateDefinition = new Update().inc("reply", 1);
        mongoTemplate.updateFirst(query,updateDefinition,ApComment.class);

        return ResponseResult.okResult("评论成功");
    }

    /**
     * 点赞评论方法
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult like(CommentRepayLikeDto dto) {
        //1.检查参数
        if (dto.getCommentRepayId() == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        //2.判断是否登录
        ApUser user = AppThreadLocal.getApUser();
        if (user == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        //3.判断评论是否存在
        ApComment comment = mongoTemplate.findById(dto.getCommentRepayId(), ApComment.class);
        if (comment == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
        }

        //4.点赞操作，
        //设置redis的key
        String key="COMMENT_REPAY_LIKE_"+user.getId();
        //检查redis中是否包含该评论id
        Boolean member = redisTemplate.opsForSet().isMember(key, dto.getCommentRepayId());
        //4.1 已经包含评论信息，表示已经点赞过，   再次点赞操作
        if(member && dto.getOperation()==0){
            return ResponseResult.okResult(AppHttpCodeEnum.DATA_EXIST);
        }
        //4.2 已经点赞过 ， 取消点赞
        if(member && dto.getOperation()==1){
            //删除redis中点赞数据
            redisTemplate.opsForSet().remove(key, dto.getCommentRepayId());
            //删除mongo中的点赞数据
            mongoTemplate.remove(
                    Query.query(Criteria.where("userId").is(user.getId()).and("targetId").is(dto.getCommentRepayId())),
                    ApCommentLike.class);

            //更新mongo中的评论表中的点赞数量 -1
            //update 表 set likes=lieks-1 where id=? and likes>0
            Query query=Query.query(Criteria.where("id").is(comment.getId()).and("likes").gt(0));
            UpdateDefinition updateDefinition=new Update().inc("likes",-1);
            mongoTemplate.updateFirst(query, updateDefinition,ApComment.class);

        }
        //4.3 没有点赞过，点赞
        if(!member && dto.getOperation()==0){
            //保存redis中点赞数据
            redisTemplate.opsForSet().add(key,dto.getCommentRepayId());
            //保存点赞数据到mongodb中
            ApCommentLike commentLike = new ApCommentLike();
            commentLike.setId(ObjectId.get().toHexString());
            commentLike.setTargetId(dto.getCommentRepayId());
            commentLike.setUserId(user.getId());
            commentLike.setCreatedTime(new Date());

            mongoTemplate.save(commentLike);
            //更新mongo中的评论表中的点赞数量+1
            Query query=Query.query(Criteria.where("id").is(comment.getId()));
            UpdateDefinition updateDefinition=new Update().inc("likes",1);
            mongoTemplate.updateFirst(query, updateDefinition,ApComment.class);
        }

        //5.查询评论表中的最新评论数据中的点赞数量返回给前台
        comment = mongoTemplate.findById(comment.getId(), ApComment.class);

        //6.返回数据，注意必须返回一个likes给前台，因为要展示点赞数量
        Map resultMap=new HashMap();
        resultMap.put("likes",comment.getLikes());
        return ResponseResult.okResult(resultMap);
    }

    /**
     * 根据评论id去查询所有的评论回复
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult load(CommentRepayListDto dto) {
        //1.检查参数
        if (dto.getCommentId() == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }

        if (dto.getSize() == null || dto.getSize() == 0) {
            dto.setSize(10);
        }
        dto.setSize(Math.min(dto.getSize(), 50));

        //2根据文章id去查询mongo的评论表，并进行分页和排序展示
        Query query=Query.query(Criteria.where("targetId").is(dto.getCommentId())
                .and("createdTime").lt(dto.getMinDate()))
                .with(Sort.by(Sort.Direction.DESC,"createdTime")) //排序
                .limit(dto.getSize()); //分页
        List<ApComment> commentList = mongoTemplate.find(query, ApComment.class);
        if(commentList==null && commentList.size()<0){
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
        }

        //3.如果此刻是游客登录的话，则直接返回评论列表
        ApUser user = AppThreadLocal.getApUser();
        if(user.getId()==0){
            return ResponseResult.okResult(commentList);
        }
        //4.否则就是用户登录，加载数据的时候，要判断当前用户点赞了拿些评论，并给予标识
        //4.1 查询redis中是否有点赞数据
        String key="COMMENT_REPAY_LIKE_"+user.getId();
        //根据key查询出所有的值
        Set<String> like_ids = redisTemplate.opsForSet().members(key);
        //4.2 如果没有查询到数据,则直接返回评论列表
        if(like_ids==null){
            return ResponseResult.okResult(commentList);
        }
        //4.3 否则，就是存在点赞数据，则添加标记
        List<ApCommentVo> resultList = commentList.stream().map(comment -> {
            ApCommentVo vo = new ApCommentVo();
            BeanUtils.copyProperties(comment, vo);
            if (like_ids.contains(comment.getId())) {
                vo.setOperation((short) 0);
            }
            return vo;

        }).collect(Collectors.toList());
        //5. 返回数据

        return ResponseResult.okResult(resultList);
    }
}